Skip to content

fix(deps): bump pion/stun to v3.1.5 and pion/dtls to v3.1.4 (2 CVEs) - #1075

Merged
mudler merged 1 commit into
mudler:masterfrom
mauromorales:fix/bump-pion-stun-dtls-cves
Aug 12, 2026
Merged

fix(deps): bump pion/stun to v3.1.5 and pion/dtls to v3.1.4 (2 CVEs)#1075
mudler merged 1 commit into
mudler:masterfrom
mauromorales:fix/bump-pion-stun-dtls-cves

Conversation

@mauro-agent

Copy link
Copy Markdown
Contributor

Two transitive dependencies currently resolve to versions with published advisories:

advisory module in v0.35.3 fixed in
GHSA-34rh-wp3j-6cxc github.com/pion/stun/v3 3.1.1 3.1.5
GHSA-wg4g-wm44-ch5j github.com/pion/dtls/v3 3.1.2 3.1.4

Both are remote denial-of-service via panic while parsing malformed input — STUN messages and DTLS handshakes respectively. Both arrive transitively through go-libp2p's WebRTC transport.

This surfaced from downstream: edgevpn is bundled as a binary in every Kairos release, so these show up when scanning the shipped artifacts.

The change also carries pion/transport v4.0.1 → v4.0.2 as a dependency of the above. go.mod and go.sum only.

Testing

  • go build ./... — clean
  • go vet ./... — clean
  • go test -count=1 ./pkg/node/... — green, twice, at 13s and 10s, matching baseline timings on an unmodified checkout

(go build ./... needs api/react-ui/dist to exist for the embed; I stubbed it locally for the build check only, nothing committed.)

Two other advisories deliberately left out

The same scan flags two more, and I could not include them because their fixes break peer connectivity. I bisected each against pkg/node:

variant quic-go pion transport/stun/dtls x/text pkg/node
baseline 0.59.1 4.0.1 / 3.1.1 / 3.1.2 0.38.0 ok, 12s (×2)
x/text only 0.59.1 4.0.1 / 3.1.1 / 3.1.2 0.39.0 ok, 11s
this PR 0.59.1 4.0.2 / 3.1.5 / 3.1.4 0.38.0 ok, 13s / 10s
this PR + x/text 0.59.1 4.0.2 / 3.1.5 / 3.1.4 0.39.0 FAIL, 247s
webtransport-go only 0.60.0 4.0.1 / 3.1.1 / 3.1.2 0.38.0 FAIL
all four 0.60.0 4.0.2 / 3.1.5 / 3.1.4 0.39.0 FAIL (×3)

The failure is always the same spec — "nodes can write to the ledger" — timing out at 240s because two nodes never establish connectivity, where a passing run completes in 10–13s.

  • webtransport-go → v0.11.1 drags quic-go 0.59.1 → 0.60.0, and that alone reproduces the failure. go-libp2p pins quic-go tightly, so this probably needs a go-libp2p bump first.
  • x/text → v0.39.0 passes alone but fails combined with the pion bumps. One observation each way, so I would not call that settled — though x/text supplies IDNA, which multiaddr uses for DNS peer addresses, which is at least a plausible mechanism.

Happy to be wrong about either; the raw bisection is reproducible with the table above.


🤖 Prepared by mauro-agent, an AI agent operated by @mauromorales, from his fork and with his review. The bisection and testing above were run by the agent; the decision to send this is his.

Both are pulled in transitively through go-libp2p's WebRTC transport and
both currently resolve to versions with published advisories:

  GHSA-34rh-wp3j-6cxc  pion/stun  remote DoS via panic while parsing a
                                  malformed STUN message    (fixed 3.1.5)
  GHSA-wg4g-wm44-ch5j  pion/dtls  DoS via panic while parsing a crafted
                                  handshake                 (fixed 3.1.4)

edgevpn is bundled as a binary in every Kairos release, so these surface in
downstream vulnerability scans of the shipped artifacts.

The bump also carries pion/transport v4.0.1 -> v4.0.2 as a dependency.

Verified: `go build ./...` clean, `go vet ./...` clean, and
`go test -count=1 ./pkg/node/...` green twice at 13s and 10s, matching
baseline timings on an unmodified checkout.

Deliberately limited to these two modules. Two other advisories in the same
scan were left alone because their fixes break peer connectivity:
webtransport-go v0.11.1 pulls quic-go 0.59.1 -> 0.60.0, and x/text v0.39.0
in combination with these pion bumps -- both make pkg/node's "nodes can
write to the ledger" spec time out at 240s where it otherwise passes in
about 12s. Those look like they need a go-libp2p bump first and are left
for a separate change.
mauro-agent pushed a commit to mauro-agent/kairos that referenced this pull request Aug 12, 2026
Adds an upstream-regression category for the case the existing three did not
cover: a fix is published, but taking it breaks the component.

Both advisories are in the edgevpn binary, which ships in every Kairos
release from mudler/edgevpn. Bisected against edgevpn's pkg/node suite,
which exercises real peer-to-peer connectivity. Both make the "nodes can
write to the ledger" spec time out at 240s where an unmodified checkout
passes in 10-13 seconds.

webtransport-go v0.11.1 pulls quic-go 0.59.1 -> 0.60.0 and that alone
reproduces the failure; go-libp2p pins quic-go tightly, so this likely needs
a go-libp2p bump first. x/text v0.39.0 passes alone but fails combined with
the pion bumps, and x/text supplies IDNA which multiaddr uses for DNS peer
addresses.

The two advisories in the same scan that could be taken safely are in
mudler/edgevpn#1075. These two were deliberately left out of it.

Expiry is 60 days rather than the 30 used for major-upgrade-required: the
work is in a project we do not control, so a shorter clock would redden the
gate without giving anyone an action.

Signed-off-by: Mauro Morales <contact@mauromorales.com>
@mauro-agent
mauro-agent marked this pull request as ready for review August 12, 2026 10:53
mauro-agent pushed a commit to mauro-agent/kairos that referenced this pull request Aug 12, 2026
…ing fixes

Two changes, one a real bug found while verifying the provider-kairos
v2.16.2 bump.

The guard was inverted in effect. osv-scanner's default JSON only emits
results for packages that HAVE findings, so a scan with nothing to report
produces an empty results array -- identical, to the guard, to a scan that
read no binaries at all. It would have failed every genuinely clean release,
which is the opposite of what it exists for. Adding --all-packages makes the
output list everything it read: the same bundle now reports 1425 packages
and 0 vulnerabilities, so "read nothing" and "found nothing" are finally
distinguishable.

Also adds an upstream-fix-pending category and the two advisories it covers.
Both are pion parsing DoS issues in the edgevpn binary. provider-kairos
v2.16.2 cleared its copies; the edgevpn copies need mudler/edgevpn#1075
merged and an edgevpn release before EDGEVPN_VERSION can move. Thirty days,
shorter than upstream-regression, because this one is expected to resolve.

Verified against the real bundle at provider-kairos v2.16.2: guard passes on
1425 packages, enforce passes with zero unignored advisories.

Signed-off-by: Mauro Morales <contact@mauromorales.com>
@mudler
mudler enabled auto-merge (squash) August 12, 2026 13:07
mauromorales added a commit to kairos-io/kairos that referenced this pull request Aug 12, 2026
* ci: gate releases on a vulnerability scan of the shipped bundle

Adds a scan of the binaries Kairos actually ships, for the kairos-init
version this repo pins.

The existing scanning cannot see these dependencies. kairos-init
UPX-compresses the bundled binaries, and a UPX-packed Go binary no longer
exposes its module metadata, so immucore, kairos-agent, provider-kairos and
the rest are opaque to a scanner. release.yaml's grype and trivy runs are
also report-only with grype_sarif_fail_build disabled, so a green release
says nothing about CVEs.

The job resolves ARG KAIROS_INIT from images/Dockerfile, checks kairos-init
out at that tag, runs `make download` with SKIP_UPX=true so the binaries
stay readable, and scans the result with osv-scanner. The scanned artifact
is deliberately not byte-identical to the shipped one; it is composed from
the same sources at the same pins, which is what matters for dependency
scanning.

Two scanner flags are load-bearing and are commented as such, because
without either the scan finds nothing and reports success:

  --no-ignore                      kairos-init's .gitignore excludes
                                   pkg/bundled/binaries/, and osv-scanner
                                   honours .gitignore.
  --experimental-plugins artifact  the default plugin set cannot read Go
                                   binaries at all.

A separate step fails the build when zero packages were extracted, so a
broken scan cannot pass as a clean one.

osv-scanner.toml carries the ignore list. Anything with a published,
takeable fix is meant to be bumped rather than ignored; entries are limited
to what cannot currently be fixed, each with a reason and an expiry, and an
expired entry fails the build. Expiry varies by category so the gate stays
trustworthy: 90 days where no fix exists upstream, two weeks where the only
fix is a Go prerelease, thirty days where clearing it needs a major upgrade.

Runs on pull_request so master stays releasable, and exposes workflow_call
so release.yaml can depend on it.

Refs: #3985

Signed-off-by: Mauro Morales <contact@mauromorales.com>

* ci: scope the scan triggers to releases and the files that decide the result

Review feedback: this is a release gate, so it should not run on every pull
request.

Correct, and the unscoped trigger was actively harmful. The findings belong
to the pinned dependency set, not to the change under review, so with
advisories outstanding every open PR would show a red check for CVEs its
author did not introduce and cannot fix -- including external contributors'
PRs on a public repo. New advisories are published continuously, so a PR
green yesterday would go red today for reasons unrelated to it.

workflow_call is the gate; release.yaml depends on it. workflow_dispatch
stays for manual runs. pull_request is kept but scoped to the three files
that actually determine the outcome: the kairos-init pin in
images/Dockerfile, the ignore list, and this workflow. That keeps a bad pin
bump or a bad ignore entry caught where it is relevant, and means edits to
the workflow itself are still exercised in CI, without touching any
unrelated PR.

Signed-off-by: Mauro Morales <contact@mauromorales.com>

* ci: make the scan an actual release gate

The previous commit exposed workflow_call but nothing called it, so a
workflow named "Release vulnerability scan" never ran on a release. It
gated nothing.

release.yaml and release-arm.yaml now both start with a vulnerability-scan
job, and every publishing job depends on it: core, standard-k3s and
standard-k0s on amd64, core and standard on arm64. A tag push runs the scan
first, and if the shipped bundle carries unignored advisories the factory
jobs never run, so no artifacts and no GitHub release are produced.

The scan resolves the kairos-init pin from images/Dockerfile, so it always
describes the composition of the release being cut rather than whatever is
current on master.

One scan covers both architectures. It reads Go module metadata from the
amd64 bundle, and the module set is the same across architectures because
it comes from the same sources at the same pins.

Signed-off-by: Mauro Morales <contact@mauromorales.com>

* ci: distinguish advisories from findings in the scan report

The first CI run reported "14 unignored advisories" while the scan had
found 13. The scan was right and the message was wrong.

One advisory can affect several module versions in the same bundle, because
different binaries pin different versions -- GO-2026-5970 is present at both
golang.org/x/text@0.37.0 and @0.38.0. The count was over rows, one per
(advisory, module@version) pair, and every row was being called an advisory.

Counts both now: advisories for the headline, findings for the per-module
rows, both in the error and the step summary. The gate condition is
unchanged.

Signed-off-by: Mauro Morales <contact@mauromorales.com>

* ci: ignore two advisories whose fixes break edgevpn connectivity

Adds an upstream-regression category for the case the existing three did not
cover: a fix is published, but taking it breaks the component.

Both advisories are in the edgevpn binary, which ships in every Kairos
release from mudler/edgevpn. Bisected against edgevpn's pkg/node suite,
which exercises real peer-to-peer connectivity. Both make the "nodes can
write to the ledger" spec time out at 240s where an unmodified checkout
passes in 10-13 seconds.

webtransport-go v0.11.1 pulls quic-go 0.59.1 -> 0.60.0 and that alone
reproduces the failure; go-libp2p pins quic-go tightly, so this likely needs
a go-libp2p bump first. x/text v0.39.0 passes alone but fails combined with
the pion bumps, and x/text supplies IDNA which multiaddr uses for DNS peer
addresses.

The two advisories in the same scan that could be taken safely are in
mudler/edgevpn#1075. These two were deliberately left out of it.

Expiry is 60 days rather than the 30 used for major-upgrade-required: the
work is in a project we do not control, so a shorter clock would redden the
gate without giving anyone an action.

Signed-off-by: Mauro Morales <contact@mauromorales.com>

* ci: fix the false-green guard failing on clean scans, ignore two pending fixes

Two changes, one a real bug found while verifying the provider-kairos
v2.16.2 bump.

The guard was inverted in effect. osv-scanner's default JSON only emits
results for packages that HAVE findings, so a scan with nothing to report
produces an empty results array -- identical, to the guard, to a scan that
read no binaries at all. It would have failed every genuinely clean release,
which is the opposite of what it exists for. Adding --all-packages makes the
output list everything it read: the same bundle now reports 1425 packages
and 0 vulnerabilities, so "read nothing" and "found nothing" are finally
distinguishable.

Also adds an upstream-fix-pending category and the two advisories it covers.
Both are pion parsing DoS issues in the edgevpn binary. provider-kairos
v2.16.2 cleared its copies; the edgevpn copies need mudler/edgevpn#1075
merged and an edgevpn release before EDGEVPN_VERSION can move. Thirty days,
shorter than upstream-regression, because this one is expected to resolve.

Verified against the real bundle at provider-kairos v2.16.2: guard passes on
1425 packages, enforce passes with zero unignored advisories.

Signed-off-by: Mauro Morales <contact@mauromorales.com>

---------

Signed-off-by: Mauro Morales <contact@mauromorales.com>
Co-authored-by: Mauro Morales <contact@mauromorales.com>
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 39.32%. Comparing base (689c89a) to head (5eaf9cf).
⚠️ Report is 778 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1075      +/-   ##
==========================================
+ Coverage   34.32%   39.32%   +5.00%     
==========================================
  Files          26       43      +17     
  Lines        2057     2853     +796     
==========================================
+ Hits          706     1122     +416     
- Misses       1249     1577     +328     
- Partials      102      154      +52     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mudler
mudler merged commit 97f8fed into mudler:master Aug 12, 2026
6 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants